//! # 监控仪表板模块
//!
//! 提供基于 Web 的监控仪表板，包括实时指标展示、告警管理和 APM 监控视图

use crate::{
    MetricFamily, AlertManager, AlertEvent, ApmManager, PerformanceStats,
    prometheus::PrometheusExporter, AlertRule, AlertSeverity, MemoryMetricsCollector
};
use rustcloud_core::{ServiceResult, ServiceError};
use axum::{
    extract::{Path, Query, State},
    http::{StatusCode, HeaderMap},
    response::{Html, Json, Response},
    routing::{get, post, delete},
    Router,
};
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::sync::Arc;
use tokio::sync::RwLock;
use tower::ServiceBuilder;
use tower_http::cors::CorsLayer;
use tracing::{info, warn, error};

/// 仪表板配置
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DashboardConfig {
    /// 服务端口
    pub port: u16,
    /// 绑定地址
    pub bind_address: String,
    /// 是否启用
    pub enabled: bool,
    /// 刷新间隔（秒）
    pub refresh_interval: u64,
    /// 历史数据保留时间（小时）
    pub data_retention_hours: u64,
    /// 是否启用认证
    pub auth_enabled: bool,
    /// API Token
    pub api_token: Option<String>,
}

impl Default for DashboardConfig {
    fn default() -> Self {
        Self {
            port: 8090,
            bind_address: "0.0.0.0".to_string(),
            enabled: true,
            refresh_interval: 5,
            data_retention_hours: 24,
            auth_enabled: false,
            api_token: None,
        }
    }
}

/// 仪表板状态
#[derive(Clone)]
pub struct DashboardState {
    /// Prometheus 导出器
    pub prometheus_exporter: Arc<PrometheusExporter>,
    /// 告警管理器
    pub alert_manager: Arc<AlertManager>,
    /// APM 管理器
    pub apm_manager: Arc<ApmManager>,
    /// 配置
    pub config: DashboardConfig,
}

/// 仪表板服务器
pub struct DashboardServer {
    state: DashboardState,
    config: DashboardConfig,
}

/// API 响应格式
#[derive(Serialize)]
pub struct ApiResponse<T> {
    pub success: bool,
    pub data: Option<T>,
    pub error: Option<String>,
    pub timestamp: u64,
}

impl<T> ApiResponse<T> {
    pub fn success(data: T) -> Self {
        Self {
            success: true,
            data: Some(data),
            error: None,
            timestamp: std::time::SystemTime::now()
                .duration_since(std::time::UNIX_EPOCH)
                .unwrap()
                .as_secs(),
        }
    }

    pub fn error(error: String) -> Self {
        Self {
            success: false,
            data: None,
            error: Some(error),
            timestamp: std::time::SystemTime::now()
                .duration_since(std::time::UNIX_EPOCH)
                .unwrap()
                .as_secs(),
        }
    }
}

/// 查询参数
#[derive(Deserialize)]
pub struct MetricsQuery {
    /// 指标名称
    pub name: Option<String>,
    /// 标签过滤
    pub labels: Option<String>,
    /// 时间范围（分钟）
    pub range: Option<u64>,
}

/// 仪表板概览数据
#[derive(Serialize)]
pub struct DashboardOverview {
    /// 系统状态
    pub system_status: String,
    /// 活跃服务数量
    pub active_services: u32,
    /// 总指标数量
    pub total_metrics: u32,
    /// 活跃告警数量
    pub active_alerts: u32,
    /// 平均响应时间
    pub avg_response_time: f64,
    /// 错误率
    pub error_rate: f64,
    /// 系统运行时间
    pub uptime_hours: f64,
}

impl DashboardServer {
    /// 创建新的仪表板服务器
    pub fn new(
        prometheus_exporter: Arc<PrometheusExporter>,
        alert_manager: Arc<AlertManager>,
        apm_manager: Arc<ApmManager>,
        config: DashboardConfig,
    ) -> Self {
        let state = DashboardState {
            prometheus_exporter,
            alert_manager,
            apm_manager,
            config: config.clone(),
        };

        Self { state, config }
    }

    /// 启动仪表板服务器
    pub async fn start(&self) -> ServiceResult<()> {
        if !self.config.enabled {
            info!("Dashboard is disabled");
            return Ok(());
        }

        info!("Starting dashboard server on {}:{}", self.config.bind_address, self.config.port);

        let app = self.create_router();
        
        let listener = tokio::net::TcpListener::bind(format!("{}:{}", self.config.bind_address, self.config.port))
            .await
            .map_err(|e| ServiceError::InternalError(format!("Failed to bind dashboard server: {}", e)))?;

        tokio::spawn(async move {
            if let Err(e) = axum::serve(listener, app).await {
                error!("Dashboard server error: {}", e);
            }
        });

        info!("Dashboard server started successfully");
        Ok(())
    }

    /// 创建路由器
    fn create_router(&self) -> Router {
        Router::new()
            // 静态文件和 HTML 页面
            .route("/", get(dashboard_home))
            .route("/metrics", get(metrics_page))
            .route("/alerts", get(alerts_page))
            .route("/apm", get(apm_page))
            .route("/health", get(health_page))
            
            // API 端点
            .route("/api/overview", get(get_overview))
            .route("/api/metrics", get(get_metrics))
            .route("/api/metrics/search", get(search_metrics))
            .route("/api/alerts", get(get_alerts))
            .route("/api/alerts/:id", delete(delete_alert))
            .route("/api/alerts/rules", get(get_alert_rules))
            .route("/api/alerts/rules", post(create_alert_rule))
            .route("/api/apm/stats", get(get_apm_stats))
            .route("/api/apm/bottlenecks", get(get_bottlenecks))
            .route("/api/health", get(get_health_status))
            
            // WebSocket 端点（实时数据推送）
            .route("/ws/metrics", get(metrics_websocket))
            .route("/ws/alerts", get(alerts_websocket))
            
            .layer(
                ServiceBuilder::new()
                    .layer(CorsLayer::permissive())
                    .into_inner(),
            )
            .with_state(self.state.clone())
    }
}

// ============== HTML 页面处理器 ==============

/// 主页
async fn dashboard_home() -> Html<&'static str> {
    Html(include_str!("../templates/index.html"))
}

/// 指标页面
async fn metrics_page() -> Html<&'static str> {
    Html(include_str!("../templates/metrics.html"))
}

/// 告警页面
async fn alerts_page() -> Html<&'static str> {
    Html(include_str!("../templates/alerts.html"))
}

/// APM 页面
async fn apm_page() -> Html<&'static str> {
    Html(include_str!("../templates/apm.html"))
}

/// 健康检查页面
async fn health_page() -> Html<&'static str> {
    Html(include_str!("../templates/health.html"))
}

// ============== API 处理器 ==============

/// 获取仪表板概览
async fn get_overview(State(state): State<DashboardState>) -> Json<ApiResponse<DashboardOverview>> {
    // 获取指标数据
    let metrics = match state.prometheus_exporter.gather().await {
        Ok(metrics) => metrics,
        Err(e) => {
            return Json(ApiResponse::error(format!("Failed to collect metrics: {}", e)));
        }
    };

    // 获取告警数据
    let alerts = state.alert_manager.get_active_alerts().await;
    
    // 获取 APM 数据
    let apm_stats = state.apm_manager.get_performance_stats().await;

    let overview = DashboardOverview {
        system_status: if alerts.iter().any(|a| a.severity == AlertSeverity::Critical) {
            "CRITICAL".to_string()
        } else if alerts.iter().any(|a| a.severity == AlertSeverity::Error) {
            "ERROR".to_string()
        } else if alerts.iter().any(|a| a.severity == AlertSeverity::Warning) {
            "WARNING".to_string()
        } else {
            "HEALTHY".to_string()
        },
        active_services: estimate_active_services(&metrics),
        total_metrics: metrics.iter().map(|f| f.metrics.len() as u32).sum(),
        active_alerts: alerts.len() as u32,
        avg_response_time: apm_stats.avg_response_time,
        error_rate: apm_stats.error_rate,
        uptime_hours: 24.0, // TODO: 实际计算系统运行时间
    };

    Json(ApiResponse::success(overview))
}

/// 获取指标数据
async fn get_metrics(
    State(state): State<DashboardState>,
    Query(query): Query<MetricsQuery>,
) -> Json<ApiResponse<Vec<MetricFamily>>> {
    match state.prometheus_exporter.gather().await {
        Ok(mut metrics) => {
            // 根据查询参数过滤指标
            if let Some(name) = &query.name {
                metrics.retain(|m| m.name.contains(name));
            }

            Json(ApiResponse::success(metrics))
        }
        Err(e) => Json(ApiResponse::error(format!("Failed to collect metrics: {}", e))),
    }
}

/// 搜索指标
async fn search_metrics(
    State(state): State<DashboardState>,
    Query(query): Query<MetricsQuery>,
) -> Json<ApiResponse<Vec<String>>> {
    match state.prometheus_exporter.gather().await {
        Ok(metrics) => {
            let mut metric_names: Vec<String> = metrics.iter().map(|m| m.name.clone()).collect();
            
            // 根据查询参数过滤
            if let Some(name) = &query.name {
                metric_names.retain(|n| n.contains(name));
            }
            
            metric_names.sort();
            metric_names.dedup();
            
            Json(ApiResponse::success(metric_names))
        }
        Err(e) => Json(ApiResponse::error(format!("Failed to search metrics: {}", e))),
    }
}

/// 获取告警列表
async fn get_alerts(State(state): State<DashboardState>) -> Json<ApiResponse<Vec<AlertEvent>>> {
    let alerts = state.alert_manager.get_active_alerts().await;
    Json(ApiResponse::success(alerts))
}

/// 删除告警
async fn delete_alert(
    State(_state): State<DashboardState>,
    Path(alert_id): Path<String>,
) -> Json<ApiResponse<String>> {
    // TODO: 实现告警删除逻辑
    Json(ApiResponse::success(format!("Alert {} deleted", alert_id)))
}

/// 获取告警规则
async fn get_alert_rules(State(_state): State<DashboardState>) -> Json<ApiResponse<Vec<AlertRule>>> {
    // TODO: 实现获取告警规则逻辑
    Json(ApiResponse::success(vec![]))
}

/// 创建告警规则
async fn create_alert_rule(
    State(_state): State<DashboardState>,
    Json(rule): Json<AlertRule>,
) -> Json<ApiResponse<String>> {
    // TODO: 实现创建告警规则逻辑
    Json(ApiResponse::success(format!("Alert rule {} created", rule.name)))
}

/// 获取 APM 统计
async fn get_apm_stats(State(state): State<DashboardState>) -> Json<ApiResponse<PerformanceStats>> {
    let stats = state.apm_manager.get_performance_stats().await;
    Json(ApiResponse::success(stats))
}

/// 获取瓶颈报告
async fn get_bottlenecks(State(state): State<DashboardState>) -> Json<ApiResponse<Vec<crate::BottleneckReport>>> {
    let reports = state.apm_manager.get_bottleneck_reports().await;
    Json(ApiResponse::success(reports))
}

/// 获取健康状态
async fn get_health_status(State(_state): State<DashboardState>) -> Json<ApiResponse<HashMap<String, String>>> {
    let mut health = HashMap::new();
    health.insert("status".to_string(), "healthy".to_string());
    health.insert("timestamp".to_string(), 
        std::time::SystemTime::now()
            .duration_since(std::time::UNIX_EPOCH)
            .unwrap()
            .as_secs()
            .to_string()
    );
    Json(ApiResponse::success(health))
}

// ============== WebSocket 处理器 ==============

/// 指标 WebSocket
async fn metrics_websocket() -> Response {
    // TODO: 实现 WebSocket 连接，用于实时推送指标数据
    Response::builder()
        .status(StatusCode::NOT_IMPLEMENTED)
        .body("WebSocket not implemented yet".into())
        .unwrap()
}

/// 告警 WebSocket
async fn alerts_websocket() -> Response {
    // TODO: 实现 WebSocket 连接，用于实时推送告警数据
    Response::builder()
        .status(StatusCode::NOT_IMPLEMENTED)
        .body("WebSocket not implemented yet".into())
        .unwrap()
}

// ============== 辅助函数 ==============

/// 估算活跃服务数量
fn estimate_active_services(metrics: &[MetricFamily]) -> u32 {
    let mut services = std::collections::HashSet::new();
    
    for metric_family in metrics {
        for metric in &metric_family.metrics {
            if let Some(service) = metric.labels.get("service") {
                services.insert(service.clone());
            }
        }
    }
    
    services.len() as u32
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::{MemoryMetricsCollector, AlertManagerConfig};
    use std::sync::Arc;

    #[tokio::test]
    async fn test_dashboard_creation() {
        let collector = Arc::new(MemoryMetricsCollector::new());
        let prometheus_exporter = Arc::new(PrometheusExporter::new(collector));
        let alert_manager = Arc::new(AlertManager::new(AlertManagerConfig::default()));
        let apm_manager = Arc::new(ApmManager::new(crate::ApmConfig::default()));
        let config = DashboardConfig::default();

        let dashboard = DashboardServer::new(
            prometheus_exporter,
            alert_manager,
            apm_manager,
            config,
        );

        // 测试路由器创建
        let router = dashboard.create_router();
        assert!(!format!("{:?}", router).is_empty());
    }

    #[test]
    fn test_api_response() {
        let success_response = ApiResponse::success("test data");
        assert!(success_response.success);
        assert!(success_response.data.is_some());
        assert!(success_response.error.is_none());

        let error_response: ApiResponse<String> = ApiResponse::error("test error".to_string());
        assert!(!error_response.success);
        assert!(error_response.data.is_none());
        assert!(error_response.error.is_some());
    }

    #[test]
    fn test_estimate_active_services() {
        use crate::{MetricFamily, Metric, MetricType, MetricValue};
        use std::collections::HashMap;
        use std::time::SystemTime;

        let mut labels1 = HashMap::new();
        labels1.insert("service".to_string(), "user-service".to_string());
        
        let mut labels2 = HashMap::new();
        labels2.insert("service".to_string(), "order-service".to_string());

        let metrics = vec![
            MetricFamily {
                name: "http_requests_total".to_string(),
                help: "Total HTTP requests".to_string(),
                metric_type: MetricType::Counter,
                metrics: vec![
                    Metric {
                        name: "http_requests_total".to_string(),
                        help: "Total HTTP requests".to_string(),
                        metric_type: MetricType::Counter,
                        value: MetricValue::Counter(100.0),
                        labels: labels1,
                        timestamp: SystemTime::now(),
                    },
                    Metric {
                        name: "http_requests_total".to_string(),
                        help: "Total HTTP requests".to_string(),
                        metric_type: MetricType::Counter,
                        value: MetricValue::Counter(200.0),
                        labels: labels2,
                        timestamp: SystemTime::now(),
                    },
                ],
            }
        ];

        let service_count = estimate_active_services(&metrics);
        assert_eq!(service_count, 2);
    }
}